<template>
	<a-modal
		:visible="visible"
		:width="simpleStatus || showType === 0 ? 300 : 600"
		:title="title"
		:dialog-style="{ color: '#F00' }"
		:mask-style="{ color: '#00F' }"
		:wrap-style="{
			left: 'auto',
			right: `calc(50vw + ${simpleStatus || showType === 0 ? 150 : 300}px)`,
			top: '10vh',
			bottom: 'auto',
			width: 0,
			height: 0,
			color: '#0F0',
			overflow: 'visible'
		}"
		:body-style="{ background: 'rgba(0, 0, 0, 0.1)' }"
		:destroy-on-close="false"
		:footer="null"
		:mask="false"
		:centere="true"
		@cancel="close"
	>
		<a-spin
			:spinning="(is4GMethod && ewaytel.isConnecting) || !!ewaytel.telInstance?.switchCardStatus"
			:tip="!!ewaytel.telInstance?.switchCardStatus ? '正在切卡，请稍后' : '话机连接中'"
		>
			<div class="flex justify-between items-start mr-[30px] select-none">
				<line-head
					:disabled="showType === 1 && !ewaytel.isTalkIdle && !ewaytel.telInstance?.otherCallStatus"
					@onLaunch="onLaunch"
				></line-head>
				<drag-outlined ref="moveIconRef" class="mt-[-6px] text-[20px] text-blue-500 cursor-pointer" />
			</div>

			<a-spin :spinning="is4GMethod && !ewaytel.isTalkIdle && ewaytel.telInstance?.otherCallStatus" tip="话机忙碌中">
				<!-- 内容 -->
				<template v-if="!isError">
					<!-- 拨号盘 -->
					<div v-if="!showType">
						<keyboard ref="keyboardRef" v-model:phone="phoneData.phone" @onPhoneConnect="onManualCall" />
					</div>
					<!-- 通话页 -->
					<a-row v-else type="flex">
						<a-col :flex="simpleStatus ? '1' : '3'" class="section">
							<!-- 号码展示 -->
							<div class="phone">{{ phoneFormatter }}</div>
							<template v-if="!ewaytel.telInstance?.otherCallStatus">
								<!-- 时长展示 -->
								<div v-if="is4GMethod && !!talkTimeText" class="talk-time">{{ talkTimeText }}</div>
								<!-- 状态 -->
								<phone-filled v-if="['hanguping', 'hangup'].includes(ewaytel.talkState)" class="phone-hangup" />
								<svg-icon
									v-else-if="
										(store.isLineCall && store.phoneStatus) ||
										(is4GMethod && (!ewaytel.isTalkIdle || !ewaytel.telInstance?.actionType))
									"
									name="phone-status"
									class="phone-status"
								/>
							</template>
							<!-- 按钮 -->
							<div class="flex justify-center items-center gap-4">
								<span
									v-if="
										is4GMethod && !['idle', 'hangup'].includes(ewaytel.talkState) && !ewaytel.telInstance?.actionType
									"
									><svg-icon name="phone-off" class="phone-off" @click="onHangup"
								/></span>
								<template
									v-if="
										(!is4GMethod && !store.phoneStatus) ||
										(is4GMethod &&
											ewaytel.telInstance?.actionType &&
											(ewaytel.isTalkIdle || ewaytel.telInstance?.otherCallStatus))
									"
								>
									<span><svg-icon name="keyboard" class="keyboard" @click="onKeyboardOpen" /></span>
									<span><svg-icon name="phone-off" class="phone-call" @click="onManualCall" /></span>
								</template>
							</div>
							<!-- <div v-else class="keyword"></div> -->
						</a-col>
						<a-col v-if="!simpleStatus" flex="4" class="section" :offset="1">
							<div>
								<div class="name text-center">{{ phoneData.name }}</div>

								<div v-if="![0, 1, 5].includes(phoneData.type)" class="w-[100%] mt-[10px] flex flex-wrap">
									<div class="flex mr-[10px] mb-[12px]">
										<span class="w-[28px] text-gray-500">
											<span>标签</span>
										</span>
										<span class="ml-[8px]">
											<tag-list-space :list="store.tagNameList" :show-num="2" />
										</span>
									</div>
									<el-space :size="2" class="mb-[12px] cursor-pointer">
										<el-icon size="20" color="#409eff">
											<el-icon-Edit />
										</el-icon>
										<el-text class="mx-1" type="primary" @click="onTagAdd">打标签</el-text>
									</el-space>
								</div>
							</div>

							<div class="transfer-wrap">
								<template v-if="[2, 3, 4, 5].includes(phoneData.type)">
									<div class="mb-5">跟进状态</div>
									<div class="status">
										{{ followUpStatus(phoneData.status) }}
									</div>
								</template>

								<!-- 	v-if="[1, 4].includes(phoneData.type) && !disabledTransferBnt" -->
								<a-button v-if="[1, 4].includes(phoneData.type)" type="primary" @click="onTransfer">转客户</a-button>
							</div>
						</a-col>
					</a-row>
				</template>
				<!-- 错误页 -->
				<error-page v-else :type="store.phoneMethod"></error-page>
			</a-spin>
		</a-spin>

		<template #modalRender="{ originVNode }">
			<div :style="transformStyle">
				<component :is="originVNode" />
			</div>
		</template>
	</a-modal>
</template>

<script setup>
	import { message } from 'ant-design-vue'
	import tool from '@/utils/tool'

	import claimApi from '@/api/biz/claimApi'
	import { globalStore, ewaytelStore } from '@/store'
	import Keyboard from './keyboard.vue'
	import { followUpMap } from '@/views/biz/contractManagement/enum/contractEnum'

	import { useDraggable, useWindowSize } from '@vueuse/core'
	import { onBeforeRouteUpdate, useRoute } from 'vue-router'

	const store = globalStore()
	const ewaytel = ewaytelStore()

	const route = useRoute()

	const emits = defineEmits(['onTransfer'])

	const visibilitychange = (e) => {
		if (document.visibilityState === 'visible') {
			// console.log('页面回来时触发')
			if (ewaytel.telInstance) {
				if (!ewaytel.telInstance.webSocketId) {
					ewaytel.telInstance.webSocketId = new Date().getTime()
				}
				tool.data.set('WEBSOCKET_ID', ewaytel.telInstance.webSocketId)
			}
		} else if (document.visibilityState === 'hidden') {
			// console.log('页面离开时触发')
		}
	}
	const beforeunload = () => {
		ewaytel.telInstance?.reportCloseWs()
		// ewaytel.close()
	}

	onBeforeMount(() => {
		document.addEventListener('visibilitychange', visibilitychange)
		// document.addEventListener('beforeunload', beforeunload)
		window.onbeforeunload = beforeunload

		claimApi
			.get4GConfig({
				tenantId: tool.data.get('loginData').tenantId
			})
			.then(async (res) => {
				const d = res
				const communicationType =
					d.communicationTypeSwitch === 0
						? d.communicationType
							? d.communicationType.split(',').map((item) => parseInt(item))
							: null
						: null
				ewaytel.setConfigs({
					communicationTypeSwitch: d.communicationTypeSwitch,
					communicationType: communicationType,
					maxContinuousNum: d.sequentialCardChangeSwitch === 0 ? d.sequentialCardChangeLimit : null,
					callInterval: d.dialingIntervalSwitch === 0 ? d.dialingInterval : null
				})

				// 初始化可选通话方式
				if (d.communicationTypeSwitch || !communicationType) return

				const initCommunicationType = () => {
					if (communicationType.includes(1)) {
						// 4G拨号
						store.setPhoneMethod('2')
					} else if (communicationType.includes(2)) {
						// X号外呼
						store.setPhoneMethod('3')
					} else if (communicationType.includes(0)) {
						// 线路外呼
						store.setPhoneMethod('1')
					}
				}

				let phoneMethod = store.phoneMethod
				if (phoneMethod) {
					phoneMethod = parseInt(phoneMethod) - 1
					if (!communicationType.includes(phoneMethod)) {
						initCommunicationType()
					}
				} else {
					initCommunicationType()
				}

				if (store.isLineCall) return

				try {
					await ewaytel.initSocket(save4GInfo)
				} catch (err) {
					console.log(err)
				}
			})
	})
	onBeforeUnmount(() => {
		document.removeEventListener('visibilitychange', visibilitychange)
		// document.removeEventListener('beforeunload', beforeunload)
	})
	// 使用 onBeforeRouteUpdate 守卫器来监听路由变化
	onBeforeRouteUpdate((to, from) => {
		if (showType.value) {
			disabledTransferBnt.value = true // 恢复的暂不支持转客户
			store.setTransferStatus(false)
		}
	})

	const visible = ref(false)
	const defaultPhoneData = {
		phone: '',
		type: 0,
		name: '',
		status: '',
		id: null,
		code: null
	}
	const phoneData = reactive({ ...defaultPhoneData })
	const showType = ref(0)
	const title = ref('')
	const callClaimError = ref(false)
	const disabledTransferBnt = ref(false)
	const keyboardRef = ref(null)

	const setShowType = (value) => {
		showType.value = value
	}

	const simpleStatus = computed(() => phoneData.type === 0)
	const followUpStatus = (status) => {
		return followUpMap[status] || ''
	}
	const phoneFormatter = computed(() => {
		if (phoneData.phone) {
			return phoneData.phone.replace(/(\d{3})(\d{4})(\d{4})/, '$1 $2 $3')
		}
	})
	const is4GMethod = computed(() => store.is4GCall)
	const isError = computed(() => {
		if (is4GMethod.value) {
			return ewaytel.isConnectFail
		} else {
			return callClaimError.value
		}
	})

	const messageTip = () => {
		if (ewaytel.talkState === 'outgoing') {
			return message.warning('您有通话正在呼出！')
		}
		if (ewaytel.talkState === 'incoming') {
			return message.warning('您有通话正在呼入！')
		}
		if (ewaytel.talkState === 'ringback') {
			return message.warning('您有通话正在振铃！')
		}
		return message.warning('您有通话正在进行中！')
	}

	const open = async ({ id = null, code = null, phone, name, status = null, type }) => {
		console.log(
			'dialOpen',
			ewaytel.isTalkIdle,
			visible.value,
			phoneData,
			id,
			type,
			store.phoneData,
			ewaytel.telInstance
		)

		if (ewaytel.configs.communicationTypeSwitch) {
			return message.warning('请先开启并设置通讯方式')
		} else {
			if (!ewaytel.configs.communicationType) {
				return message.warning('请先设置通讯方式')
			}
		}

		if (
			!visible.value &&
			((store.isLineCall && !store.phoneStatus) || (store.is4GCall && !ewaytel.isTalkIdle)) &&
			store.phoneData &&
			(!id || id === store.phoneData.id)
		) {
			Object.assign(phoneData, store.phoneData)
			if (is4GMethod.value) {
				ewaytel.telInstance.actionType = 0
				ewaytel.telInstance.otherCallStatus = false
			}
			showType.value = 1
			visible.value = true
			return
		}

		if (store.is4GCall) {
			if (!ewaytel.isTalkIdle) {
				if (visible.value) {
					if (!type) {
						return
					} else {
						if (phone === phoneData.phone && code === phoneData.code) {
							return
						} else {
							return messageTip()
						}
					}
				} else {
					if (!type) {
						if (!ewaytel.isTalkIdle && ewaytel.telInstance?.actionType && !phoneData.phone) {
							return messageTip()
						}
						visible.value = true
						return
					} else {
						if (phone === phoneData.phone && code === phoneData.code) {
							visible.value = true
							return
						}
						return messageTip()
					}
				}
			}

			const runStatus = resetConnectStatus()
			if (!runStatus) return
		} else if (store.isLineCall) {
			if (store.phoneStatus) {
				return messageTip()
			}
		}

		const values = ewaytel.isTalkIdle
			? {
					phone,
					name,
					status,
					type, // 0-顶部拨号 1-领取 2-客户私海 3-客户公海 4-线索私海 5-线索公海
					id,
					code
			  }
			: store.phoneData
		Object.assign(phoneData, values)
		showType.value = Math.min(1, values.type)
		visible.value = true
		disabledTransferBnt.value = false

		await restart4GConnect()

		if (values.type && (!is4GMethod.value || ewaytel.isConnectSuccess)) {
			store.setPhoneData(phoneData)
			onCall()
		}
	}
	const close = () => {
		visible.value = false
		if (!showType.value) {
			keyboardRef.value?.clearValidate()
		}
		nextTick(() => {
			if (is4GMethod.value) {
				if (
					(ewaytel.isTalkIdle && (ewaytel.telInstance?.actionType || !ewaytel.isConnectSuccess)) ||
					ewaytel.telInstance?.otherCallStatus
				) {
					setTimeout(() => {
						store.setPhoneData(null)
						if (!store.autoDialStatus) {
							Object.assign(phoneData, defaultPhoneData)
						}
					}, 200)
				}
			} else {
				callClaimError.value = false
				store.setPhoneData(null)
				store.setPhoneStatus(false)
			}
		})
	}

	// 拨打
	const dialWait = ref(0)
	const setDialWait = (millisecond) => {
		dialWait.value = millisecond
	}
	const onCall = () => {
		if (is4GMethod.value) {
			const timer = setTimeout(() => {
				clearTimeout(timer)
				call4G()
			}, dialWait.value)
		} else {
			callClaim()
		}
	}
	const callClaim = async () => {
		callClaimError.value = false
		store.setPhoneStatus(true)
		const param = {
			tokerDetailId: phoneData.id,
			customerCode: phoneData.code,
			userphone: phoneData.phone,
			type: phoneData.type
		}
		try {
			await claimApi.call(param)
		} catch {
			callClaimError.value = true
			store.setPhoneStatus(false)
		}
	}
	const call4G = async () => {
		const { id, code, phone, type } = phoneData

		// 防封卡检查
		try {
			await claimApi.check4GPhone({ phone })
			await claimApi.s4GCheck({
				tenantId: tool.data.get('loginData').tenantId,
				contactPhone: phone,
				accountId: tool.data.get('USER_INFO').id
			})
		} catch (err) {
			console.log(err)
			return
		}

		// 拨号间隔检查
		if (ewaytel.configs.callInterval !== null && !!ewaytel.dialEndTime) {
			const curTime = new Date()
			const diff = curTime.getTime() - ewaytel.dialEndTime.getTime()
			if (Math.floor(diff / 1000) < ewaytel.configs.callInterval) {
				message.warning('拨号间隔不足' + ewaytel.configs.callInterval + '秒，请稍后！')
				return
			}
		}

		ewaytel.dial(phone)
	}
	const save4GInfo = (result, isCall) => {
		nextTick(async () => {
			const { id, code, phone, type } = phoneData

			// 过滤话机偶尔抽风返回的错误状态
			const resultData = JSON.parse(result)
			if (ewaytel.isTalkIdle && resultData.realtimestate === 'ringback' && !resultData.number) return
			if (
				!ewaytel.telInstance?.actionType &&
				ewaytel.talkState !== 'hangup' &&
				resultData.realtimestate === 'idle' &&
				!resultData.number
			)
				return

			// 过滤无效提交或其他浏览器账号拨打电话响应
			if ((isCall && ewaytel.isConnectSuccess) || ewaytel.telInstance?.otherCallStatus) {
				return
			}

			await claimApi.set4GDatainfo({
				tokerDetailId: id,
				customerCode: code,
				userphone: phone,
				type,
				result,
				isCall
			})
		})
	}

	//-----  通话时长及状态处理 -------//
	const talkTimeText = computed(() => {
		switch (ewaytel.talkState) {
			case 'outgoing':
				return '正在呼叫'
			case 'ringback':
				return '正在振铃'
			case 'outconnected':
				return ewaytel.talkTime
			case 'hanguping':
				return '正在挂断'
			case 'hangup':
				return '通话结束'
			default:
				return null
		}
	})

	watch(talkTimeText, (newValue, oldValue) => {
		if (newValue === '通话结束') {
			setTimeout(() => {
				if (!phoneData.type) {
					onKeyboardOpen()
				}
			}, 200)
		}
	})

	// 操作
	const onKeyboardOpen = () => {
		showType.value = 0
		Object.assign(phoneData, defaultPhoneData)
	}
	const onManualCall = async () => {
		if ((is4GMethod.value && !ewaytel.isTalkIdle) || store.phoneStatus) {
			return messageTip()
		}

		showType.value = 1
		store.setPhoneData(phoneData)
		onCall()
	}
	const onTransfer = async () => {
		const { code, type } = phoneData
		store.transferCode = code
		if (type === 1) {
			store.transferType = 0
		} else if (type === 4) {
			store.transferType = 6
			store.transferPersonData = !['clueManagement', 'clueDetail'].includes(route.name)
				? await claimApi.getCompanyPersons({
						code
				  })
				: []
			store.transferList = []
		}
		// console.log(store.transferType, store.transferCode, store.transferPersonData, store.transferList)
		store.setTransferStatus(true)
	}
	const onHangup = () => {
		store.setPhoneData(null)
		ewaytel.hangup()
	}
	const onLaunch = (val) => {
		if (val === '1') {
			// 线路
			callClaimError.value = false
		} else if (val === '2') {
			// 4G
			const runStatus = resetConnectStatus()
			if (!runStatus) return
		}

		restart4GConnect()
	}

	const resetConnectStatus = () => {
		if (!ewaytel.telInstance) {
			return true
		}

		if (ewaytel.isConnecting) {
			return false
		}
		if (ewaytel.isConnectFail) {
			ewaytel.connectedstate = '0'
		}
		return true
	}

	const restart4GConnect = async () => {
		if (is4GMethod.value && ewaytel.isConnecting) {
			try {
				await ewaytel.initSocket(save4GInfo)
			} catch (err) {
				console.log(err)
			}
		}
	}

	/**
	 * 打标签
	 */
	const onTagAdd = () => {
		store.tagSimple = true
		store.tagShowTab = false
		store.tagNode?.open(phoneData.code, phoneData.type, store.tagIdList)
	}

	// 拖拽
	const moveIconRef = ref(null)
	const { x, y, isDragging } = useDraggable(moveIconRef)
	const { width, height } = useWindowSize()
	const startX = ref(0)
	const startY = ref(0)
	const startedDrag = ref(false)
	const transformX = ref(0)
	const transformY = ref(0)
	const preTransformX = ref(0)
	const preTransformY = ref(0)
	const dragRect = ref({
		left: 0,
		right: 0,
		top: 0,
		bottom: 0
	})
	watch([x, y], () => {
		if (!startedDrag.value) {
			startX.value = x.value
			startY.value = y.value
			const bodyRect = document.body.getBoundingClientRect()
			const titleRect = moveIconRef.value.getBoundingClientRect()
			dragRect.value.right = bodyRect.width - titleRect.width
			dragRect.value.bottom = bodyRect.height - titleRect.height
			preTransformX.value = transformX.value
			preTransformY.value = transformY.value
		}
		startedDrag.value = true
	})
	watch(isDragging, () => {
		if (!isDragging.value) {
			startedDrag.value = false
		}
		document.body.onselectstart = () => !isDragging.value
	})
	watchEffect(() => {
		if (startedDrag.value) {
			transformX.value =
				preTransformX.value + Math.min(Math.max(dragRect.value.left, x.value), dragRect.value.right) - startX.value
			transformY.value =
				preTransformY.value + Math.min(Math.max(dragRect.value.top, y.value), dragRect.value.bottom) - startY.value
		}
	})
	watch([width, height], () => {
		if (moveIconRef.value) {
			startX.value = 0
			startY.value = 0
			startedDrag.value = false
			transformX.value = 0
			transformY.value = 0
			preTransformX.value = 0
			preTransformY.value = 0
			dragRect.value = {
				left: 0,
				right: 0,
				top: 0,
				bottom: 0
			}
		}
	})
	const transformStyle = computed(() => {
		return {
			transform: `translate(${transformX.value}px, ${transformY.value}px)`
		}
	})

	defineExpose({
		visible,
		phoneData,
		open,
		close,
		setShowType,
		setDialWait
	})
</script>

<style lang="less" scoped>
	.section {
		display: flex;
		flex-direction: column;
		justify-content: space-between;
		align-items: center;
		height: 280px;
		.phone {
			font-size: 24px;
			font-weight: bold;
		}
		.phone-status {
			font-size: 90px;
		}
		.phone-hangup {
			font-size: 90px;
			transform: rotate(225deg);
		}
		.keyboard {
			font-size: 60px;
			cursor: pointer;
		}
		.phone-off {
			cursor: pointer;
			background-color: red;
			border-radius: 4px;
			padding: 8px;
			width: 55px;
			height: 35px;
		}
		.phone-call {
			cursor: pointer;
			background-color: #3d7fff;
			border-radius: 4px;
			padding: 8px;
			width: 55px;
			height: 35px;
		}
		.name {
			font-size: 24px;
			font-weight: 600;
		}

		.transfer-wrap {
			margin-bottom: 20px;
			.status {
				margin-bottom: 30px;
				font-size: 20px;
			}
		}
		.talk-time {
			color: #ababab;
			font-size: 12px;
			text-align: center;
			margin-top: -28px;
		}
	}
</style>
